package cn.yeziji.netty.factory;

import cn.yeziji.forum.common.key.MessageKey;
import cn.yeziji.netty.adapter.CommunicationAdapters;
import cn.yeziji.netty.enums.MessageClusterEnum;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

/**
 * 消息代理工厂
 *
 * @author gzkemays
 * @since 2022/11/08 12:38 PM
 */
public class MessageHandleFactory {
  final Map<Integer, MessageClusterEnum> CLUSTER_ENUM_MAP =
      new HashMap<Integer, MessageClusterEnum>() {
        {
          put(MessageKey.HEART_FLAG, MessageClusterEnum.HEART);
          put(MessageKey.LOG_OUT_FLAG, MessageClusterEnum.USER_LOG_OUT);
          put(MessageKey.LOGIN_FLAG, MessageClusterEnum.USER_LOGIN);
          put(MessageKey.PUBLIC_CHAT_FLAG, MessageClusterEnum.PUBLIC_CHAT);
          put(MessageKey.PRIVATE_CHAT_FLAG, MessageClusterEnum.PRIVATE_CHAT);
          put(MessageKey.PRIVATE_CHAT_EXIT_FLAG, MessageClusterEnum.PRIVATE_CHAT_EXIT);
          put(MessageKey.PUBLIC_CHAT_EXIT_FLAG, MessageClusterEnum.PUBLIC_CHAT_EXIT);
          put(MessageKey.GUEST_BOOK_FLAG, MessageClusterEnum.GUESTBOOK);
        }
      };

  int type;
  String text;

  public MessageHandleFactory(int type, String text) {
    this.type = type;
    this.text = text;
  }

  @SuppressWarnings("unchecked")
  public <T> T execute() {
    MessageClusterEnum clusterEnum = CLUSTER_ENUM_MAP.get(this.type);
    try {
      if (clusterEnum != null) {
        // 构造有参对象
        Constructor<? extends CommunicationAdapters> constructor =
            clusterEnum.getClusterAdapterClass().getConstructor(Integer.class, String.class);
        CommunicationAdapters adapters = constructor.newInstance(type, text);
        // 加入代理
        InvocationHandler handler = new MessageInvocationHandler(adapters);
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        return (T)
            Proxy.newProxyInstance(
                classLoader, new Class[] {clusterEnum.getCommunicationAdaptersClass()}, handler);
      }
    } catch (InstantiationException
        | IllegalAccessException
        | InvocationTargetException
        | NoSuchMethodException e) {
      e.printStackTrace();
      throw new RuntimeException(e);
    }
    return null;
  }
}
